package com.alex.sevice;

import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.alex.controller.System.entity.ChatCompletionChunk;
import com.alex.controller.System.entity.ChatEntity;
import com.alex.controller.System.entity.Choice;
import com.alex.controller.System.entity.RoleEntity;
import com.alex.enumType.TypeEnum;
import com.alibaba.fastjson.JSONObject;


import common.beans.User;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static common.util.StringUtil.isNotNull;


/**
 * @Author: 张福垒
 * @Date: 2024/12/25 13:28
 * @Description:
 * @phone: 13864677931
 */
@Slf4j
@Service
public class ChatGptService {


    public void ai_web_chat(HttpServletResponse responseHttp, User user, boolean insertChatRecordFlag, String contentTemp, Integer content_type, Integer startFlag) throws IOException, SQLException {


        String prefix = "";
        switch (content_type) {
            case 1:
                prefix = TypeEnum.英文学术润色.getValue();
                break;
            case 2:
                prefix = TypeEnum.中文学术润色.getValue();
                break;
            case 3:
                prefix = TypeEnum.查找语法错误.getValue();
                break;
            case 4:
                prefix = TypeEnum.中译英.getValue();
                break;
            case 5:
                prefix = TypeEnum.英译中.getValue();
                break;
            case 6:
                prefix = TypeEnum.中英互译.getValue();
                break;
            case 7:
                prefix = TypeEnum.课题发现.getValue();
                break;
            case 8:
                prefix = TypeEnum.智能诊断.getValue();
                break;
            case 9:
                prefix = TypeEnum.智能治疗.getValue();
                break;
        }

        ServletOutputStream outputStream = responseHttp.getOutputStream();
        List<ChatEntity> msgEntities = new ArrayList<>();
        //如果是聊天的,则记录表,记录回答的东西
        if (insertChatRecordFlag) {
            List<Entity> entityList = Db.use().query("SELECT * FROM chat_record WHERE user_id = " + user.getUid() + " AND deleted = 0 ;");
            if (!entityList.isEmpty()) {
                for (Entity entity : entityList) {
                    String role = entity.getStr("role");
                    String content = entity.getStr("content");
                    ChatEntity chatEntity = new ChatEntity();
                    chatEntity.setRole(role);
                    chatEntity.setContent(content);
                    msgEntities.add(chatEntity);
                }
            }
        } else {//如果是单次会话,则不做数据库记录
            ChatEntity chatEntity = new ChatEntity();
            chatEntity.setRole(RoleEntity.User);
            chatEntity.setContent(contentTemp);
            msgEntities.add(chatEntity);
        }
        //第一次使用助手 需要带提示词
        if (startFlag == 1) {
            ChatEntity chatEntity = new ChatEntity();
            chatEntity.setRole(RoleEntity.System);
            chatEntity.setContent(prefix);
            msgEntities.add(chatEntity);

            Db.use().insert(Entity.create("chat_record")
                    .set("role", RoleEntity.System)
                    .set("user_id", user.getUid())
                    .set("user_name", user.getRealname())
                    .set("unit_id", user.getGid())
                    .set("unit_name", user.getUnitName())
                    .set("content", prefix)
                    .set("content_type", content_type)
                    .set("sys_create_time", LocalDateTime.now(ZoneId.of("Asia/Shanghai")))
                    .set("sys_update_time", LocalDateTime.now(ZoneId.of("Asia/Shanghai")))
                    .set("deleted", 0));
        }

        responseHttp.setContentType("text/event-stream");
        responseHttp.setCharacterEncoding("UTF-8");
        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(20, TimeUnit.SECONDS) // 设置连接超时时间为15秒
                .readTimeout(100, TimeUnit.SECONDS)    // 设置读取超时时间为30秒
                .build();
        Request request = sendMsgAliBaBa(msgEntities);
        Response response = null;
        try {
            //解析返回回来的答案
            response = client.newCall(request).execute();
        } catch (IOException e) {
            log.error("response请求错误");
            e.printStackTrace(System.err);
        }
        if (null != response) {
            ResponseBody responseBody = response.body();
            if (null != responseBody) {
                InputStream inputStream = responseBody.byteStream();
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
                    String line = "";
                    StringBuilder stringBuilder = new StringBuilder();
                    while ((line = reader.readLine()) != null) {
                        if ("[DONE]".equals(line) || "data: [DONE]".equals(line)) {
                            break;
                        }
                        line = line.replaceAll("data: ", "").trim();
                        try {
                            if (isNotNull(line)) {
                                ChatCompletionChunk chatCompletionChunk = JSONObject.parseObject(line, ChatCompletionChunk.class);
                                List<Choice> choices = chatCompletionChunk.getChoices();
                                for (Choice choice : choices) {
                                    String content = choice.getDelta().getContent().replaceAll("\n\n", "\n");
                                    stringBuilder.append(content);
                                    outputStream.write(content.getBytes(StandardCharsets.UTF_8));
                                    outputStream.flush();
                                }
                            }

                        } catch (Exception e) {
                            e.printStackTrace(System.err);
                            log.error(e.toString());
                            outputStream.write(("\n. . . . . . .系统连接超时,请重新提问").getBytes(StandardCharsets.UTF_8));
                            outputStream.flush();
                            return;
                        }
                    }
                    if (insertChatRecordFlag) {
                        Db.use().insert(Entity.create("chat_record")
                                .set("role", RoleEntity.Assistant)
                                .set("user_id", user.getUid())
                                .set("user_name", user.getRealname())
                                .set("unit_id", user.getGid())
                                .set("unit_name", user.getUnitName())
                                .set("content", stringBuilder.toString())
                                .set("content_type", content_type)
                                .set("sys_create_time", LocalDateTime.now(ZoneId.of("Asia/Shanghai")))
                                .set("sys_update_time", LocalDateTime.now(ZoneId.of("Asia/Shanghai")))
                                .set("deleted", 0)
                        );
                    }
                } catch (Exception e) {
                    e.printStackTrace(System.err);
                }
            } else {
                outputStream.write(("\n. . . . . . .系统连接超时,请重新提问").getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
            }
        } else {
            outputStream.write(("\n. . . . . . .系统连接超时,请重新提问").getBytes(StandardCharsets.UTF_8));
            outputStream.flush();
        }
    }


    public static Request sendMsgAliBaBa(List<ChatEntity> msgEntities) {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("messages", JSONObject.toJSONString(msgEntities));
        map.put("model", "\"qwen-plus-latest\"");
        map.put("frequency_penalty", 0);
        map.put("max_tokens", 2000);
        map.put("presence_penalty", 0);
        map.put("enable_thinking", false);
        map.put("stop", null);
        map.put("stream", true);
        map.put("temperature", 1);
        map.put("top_p", 0.9);
        String string = mapToString(map);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, string);
        Request request = new Request.Builder().url("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer sk-c65ee8baf0c440238e51f74495107da3")
                .build();
        return request;
    }

    public static String mapToString(Map<String, Object> map) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("{");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (stringBuilder.length() > 1) { // 避免第一个元素前出现逗号
                stringBuilder.append(",");
            }
            String key = entry.getKey();
            Object value = entry.getValue();
            stringBuilder.append("\"").append(key).append("\":").append(value);
        }
        stringBuilder.append("}");
        return stringBuilder.toString();
    }

}
